Amazon Fargate

개요


파게이트는 서버리스 리소스의 일종으로, EKS와 같은 컨테이너 환경을 위해 제공되는 관리형 서비스이다.
컨테이너를 띄우긴 띄우는데, 서버리스로 띄우는 것이 파게이트라는 서비스다!

클러스터에서 서버리스를 쓰는 장점은 그냥 서버리스를 쓸 때의 장점과 같다.
극한의 효율로 필요한 만큼의 자원만 사용하고, 사용한 만큼만 돈을 내는 것.
(물론 서버리스 자체가 동일 스펙 대비 비용이 높기에 그렇게 좋은지는 모르겠다;)
파게이트에 올라가는 파드는 그 자체가 하나의 노드가 된다.
그래서 별도의 클러스터 오토스케일링이 필요없다는 것이 큰 장점이다.
(카펜터 믿고 쓰면 되지 않을까 싶긴 한데..)

설명

ECS에서도 파게이트를 사용하는 것이 가능하나, 나는 쿠버네티스를 기준으로 설명을 진행하고자 한다.

사용 케이스

이미 쿠버네티스 클러스터를 구축한다는 것 자체가 사실 자원을 효율적으로 사용하기 위한 것이다.
근데 여기에 왜 굳이 서버리스 환경을 들여서 또 비용 최적화를 할까?
파게이트를 써서 비용최적화를 할 수 있는 케이스가 뭐가 있을까?

흔한 사용 케이스 중 하나로, 카펜터를 파게이트에 올리는 경우가 있다.
카펜터를 사용하게 되면 카펜터가 올라간 노드는 카펜터에 의해 관리를 받으면 안 된다.
그래서 실제 운영 환경 자체는 일반 인스턴스를 쓰되, 카펜터를 인스턴스 위에 배치하지 않고 파게이트에 올림으로써 효율적으로 인스턴스 환경을 관리하는 것이다.
그리고 카펜터가 클러스터 효율화를 못 시키는 시간대가 고정돼있다면 그 때는 아예 카펜터조차 꺼버리는 식으로 비용 효율화를 할 수 있는 것이다.

두번째 사용 케이스는 일시적으로만 실행되는 워크로드를 올리는 것이다.
대표적으로 같은 것은 애초에 지속적인 프로세스가 아니므로, 순간적으로만 자원이 필요하다.
이런 것들은 일찌감치 파게이트를 활용해 정확하게 필요한 만큼만 비용을 지불하는 것이 효과적이다.
흔히 배치 파이프라인 작업, CICD 등의 작업을 할 때 파게이트를 사용하는 것은 꽤나 효과적이다.

서버리스 기술 원리

AWS의 서버리스는 Firecracker라는 툴을 기반으로 한다.[1]

파이어크래커는 KVM을 이용해 간단하게 가상 머신을 만드는 툴인데, 이로부터 호스트와의 격리를 완벽하게 해내면서도 성능을 최대한 끌어올려 아주 작은 경량의 vm을 여러 개 만들 수 있도록 한다.

파이어크래커에서 가장 신경쓰는 것이 두 가지 있다면 바로 보안과 성능이다.
이때 보안이 매우 강력한 특징 중 하나인데, 이 그림에서 보다시피 실제 vm은 이중 방벽으로 막혀있다.
일단 가상화로 인한 방벽이 하나 세워지고(이것만으로 충분한 거 아니었어..?), 여기에 seccomp, 네임스페이스 등의 리눅스의 보안 기능을 할 수 있는 모듈들로 Jailer 방벽이 세워진다.

동작 방식

스케줄링 과정

파게이트로서 서버리스 환경에 파드가 배치되는 것은 스케줄링 단계에서 정해진다.
특정 조건을 만족하는 파드가 배포된다면 Admission Webhook이 동작하여 해당 파드의 스케줄러를 fargate-scheduler로 변경해버린다.
그러면 컨트롤 플레인 어딘가의 스케줄러가 동작하며 파드를 어디에 배치할지 고른다.
이 과정에서 위에 보이는 vm 하나가 생겨나게 되며, 이 vm에 단 하나의 파드가 배치되도록 만든다.

인스턴스 스펙

image.png
이때 배치되는 파드의 자원 요청 값에 따라 인스턴스의 스펙이 정해지는데, 아무런 요청도 하지 않고 만들면 최소 값으로 지정된다.
필요한 만큼의 양을 적절하게 요청하는 것이 중요하겠다.
요청량의 값을 위의 표에 맞춰 적절히 올림하여 인스턴스가 만들어진다.
이때 내부에 따로 동작하는 데몬 프로세스 등으로 인해 실질적으로 메모리는 250메가 정도가 추가로 합산된다.[2]
즉, 만약 cpu 0.1에 메모리 0.4기가를 요청한다고 해도, 실제로는 메모리는 0.65기가로 계산되어 결과적으로 cpu 0.25, 메모리 1기가의 인스턴스가 배포될 것이다.
다만 직접적으로 노드를 보면 이 값과 다르게 출력이 될 텐데, 실제 비용에 계산되는 스펙 정보를 보려면 그 인스턴스에 배치된 파드의 어노테이션 값을 보면 된다.

스토리지로는 기본 20기가의 로컬 스토리지가 부여된다.
이것도 ephemral-storage를 통해 최대 175기가까지 높여서 받을 수 있는데, 많이 필요하다 하면 어차피 내부에 Amazon EFS 파일시스템을 부착해주니 이걸 활용하자.

인스턴스 환경

image.png
일단 파게이트가 배치되는 서브넷에는 파게이트의 ENI가 부착된다.
보다시피 요청자는 사용자가 아니며, 인스턴스 소유자 역시 마찬가지이다.
이를 통해 파게이트는 클러스터가 배포된 VPC에서 접근이 가능하게 된다.

클러스터적으로 통신이 가능한 이유는 인스턴스에 기본적으로 VPC CNI 프로세스가 동작하기 때문이다.
이 CNI는 파드에 인스턴스의 IP를 그대로 부여해주며, 그래서 실제로 뜯어보면 노드 ip와 파드 ip가 같은 것을 확인할 수 있다.
이를 통해 클러스터에 네트워크 활동을 할 수 있게 되는 것이다!

여기에 추가적으로 Fluentbit 프로세스가 동작하여, 인스턴스, 어플리케이션 로깅이 가능하게 된다.
참고로 이것 때문에 관련한 세팅을 조금 해줘야 하는데, 이건 [[#EKS 설정]]에서 본다.

주의 사항

파게이트에는 여러 가지 특징과 제한 사항이 많다.
그래서 사용할 수 있는 워크로드가 한정되니 잘 참고하자.

그러니까, 사실 안 되는 거 준내 많다.

EKS 설정

eks에서 파게이트를 쓸 때는 파게이트 프로필을 만들면 된다.
image.png
파게이트 프로필에는 네임스페이스와 라벨 셀렉터를 지정할 수 있다.
그럼 지정한 라벨이나 혹은 네임스페이스를 달아서 파드를 만들 때, 해당 파드의 정보에 따라 뮤테이팅이 발동하여 파게이트 스케줄러가 동작하게 될 것이다.
이때 파게이트의 인스턴스를 위한 롤이 액세스 엔트리에 추가된다.
image.png
테라폼 등을 활용해 직접 파게이트 프로필을 만든다면, vpc cni 정책과 pod execution 정책을 가진 롤을 만들어줘야 한다.

image.png
단순하게 파드를 배치하려고 하면 로깅 관련한 에러를 마주하게 되는데, 위와 같은 컨피그맵을 만들어주면 정상동작하게 된다.[3]

apiVersion: v1
kind: Namespace
metadata:
  labels:
    aws-observability: enabled
  name: aws-observability
spec: {}
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: aws-logging
  namespace: aws-observability
data:
  flb_log_cw: "false"  # Set to true to ship Fluent Bit process logs to CloudWatch.
  filters.conf: |
    [FILTER]
        Name parser
        Match *
        Key_name log
        Parser crio
    [FILTER]
        Name kubernetes
        Match kube.*
        Merge_Log On
        Keep_Log Off
        Buffer_Size 0
        Kube_Meta_Cache_TTL 300s
  output.conf: |
    [OUTPUT]
        Name cloudwatch_logs
        Match   kube.*
        region region-code
        log_group_name my-logs
        log_stream_prefix from-fluent-bit-
        log_retention_days 60
        auto_create_group true
  parsers.conf: |
    [PARSER]
        Name crio
        Format Regex
        Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>P|F) (?<log>.*)$
        Time_Key    time
        Time_Format %Y-%m-%dT%H:%M:%S.%L%z

이건 컨피그맵 데이터 예시이다.
여기에서 로깅 관련한 설정들을 넣어주면 된다.

coredns 설정

Core DNS를 파게이트 위에 실행하려고 하면 잘 안 될 것이다.
기본 eks에서는 core dns가 일반 인스턴스에 올라가길 기대하기 때문인데, 이에 관련한 조금의 수정이 필요하다.

kubectl patch deployment coredns -n kube-system --type json -p='[{"op": "remove", "path": "/spec/template/metadata/annotations/eks.amazonaws.com~1compute-type"}]'

어노테이션 중에 compute type에 대한 정보를 지우면 파게이트에 다시 들어가게 될 것이다.
image.png
이렇게 들어가있어도 실행이 안 될 때가 있으니 디플로이먼트를 재시작을 해보는 게 좋다.

참고


  1. https://github.com/firecracker-microvm/firecracker/tree/main ↩︎

  2. https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/fargate-pod-configuration.html ↩︎

  3. https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/fargate-logging.html ↩︎